/**
 * @file lex.c
 * @author caoml (3289436095@qq.com)
 * @brief 词法分析器
 * @version 0.1
 * @date 2022-07-07
 *
 * @copyright Copyright caoml (c) 2022
 *
 */
#include "lex.h"
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include "input_buf.h"
#include "def.h"
#include "log.h"
#include "symbol.h"
#include "keywords.h"

static const char tab_digit[] =
    {
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00 - 0x0F*/
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10 - 0x1F*/
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20 - 0x2F*/
        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30 - 0x3F*/
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40 - 0x4F*/

        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50 - 0x5F*/
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60 - 0x6F*/
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70 - 0x7F*/
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80 - 0x8F*/
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90 - 0x9F*/

        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xA0 - 0xAF*/
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xB0 - 0xBF*/
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xC0 - 0xCF*/
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xD0 - 0xDF*/
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xE0 - 0xEF*/

        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* 0xF0 - 0xFF*/
};


static const char tab_hex[] =
{
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00 - 0x0F*/
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10 - 0x1F*/
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20 - 0x2F*/
    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30 - 0x3F*/
    0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40 - 0x4F*/

    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50 - 0x5F*/
    0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60 - 0x6F*/
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70 - 0x7F*/
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80 - 0x8F*/
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90 - 0x9F*/

    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xA0 - 0xAF*/
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xB0 - 0xBF*/
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xC0 - 0xCF*/
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xD0 - 0xDF*/
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xE0 - 0xEF*/

    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* 0xF0 - 0xFF*/
};


static const char tab_hex2digit[] =
{
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00 - 0x0F*/
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10 - 0x1F*/
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20 - 0x2F*/
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30 - 0x3F*/
    0x00, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40 - 0x4F*/

    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50 - 0x5F*/
    0x00, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60 - 0x6F*/
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70 - 0x7F*/
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80 - 0x8F*/
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90 - 0x9F*/

    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xA0 - 0xAF*/
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xB0 - 0xBF*/
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xC0 - 0xCF*/
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xD0 - 0xDF*/
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xE0 - 0xEF*/

    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* 0xF0 - 0xFF*/
};

static const char tab_alpha[] =
    {
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00 - 0x0F*/
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10 - 0x1F*/
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20 - 0x2F*/
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30 - 0x3F*/
        0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* 0x40 - 0x4F*/

        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50 - 0x5F*/
        0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* 0x60 - 0x6F*/
        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70 - 0x7F*/
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80 - 0x8F*/
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90 - 0x9F*/

        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xA0 - 0xAF*/
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xB0 - 0xBF*/
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xC0 - 0xCF*/
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xD0 - 0xDF*/
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xE0 - 0xEF*/

        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* 0xF0 - 0xFF*/
};

static const char tab_id[] =
    {
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00 - 0x0F*/
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10 - 0x1F*/
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20 - 0x2F*/
        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30 - 0x3F*/
        0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* 0x40 - 0x4F*/

        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0x50 - 0x5F*/
        0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* 0x60 - 0x6F*/
        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70 - 0x7F*/
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80 - 0x8F*/
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90 - 0x9F*/

        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xA0 - 0xAF*/
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xB0 - 0xBF*/
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xC0 - 0xCF*/
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xD0 - 0xDF*/
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xE0 - 0xEF*/

        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* 0xF0 - 0xFF*/
};


static const char tab_blank[] =
    {
      /*0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, */
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, /* 0x00 - 0x0F*/
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10 - 0x1F*/
        0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20 - 0x2F*/
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30 - 0x3F*/
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40 - 0x4F*/

        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50 - 0x5F*/
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60 - 0x6F*/
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70 - 0x7F*/
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80 - 0x8F*/
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90 - 0x9F*/

        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xA0 - 0xAF*/
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xB0 - 0xBF*/
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xC0 - 0xCF*/
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xD0 - 0xDF*/
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xE0 - 0xEF*/

        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* 0xF0 - 0xFF*/
};

/**
 * @brief Get the next lex object
 *
 * @param input_buf 输入数据结构体
 * @return lex_st* NULL: 没有获取到lex; 解析得到的lex
 */
symbol_st *lex_get_symbol(
    lex_st *lex)
{
    if (lex->lookahead_symbol != NULL)
    {
        symbol_st *ret_symbol = lex->lookahead_symbol;
        lex->lookahead_symbol = NULL;
        return ret_symbol;
    }

    memset(&(lex->symbol), 0x00, sizeof(lex->symbol));

    uint8_t look_ahead;
    while (tab_blank[look_ahead = input_buf_get_char(lex->input_buf)])
    {
        if(look_ahead == '\n')
        {
            lex->line++;
        }
    }

    uint32_t name_len = 0;

    /* 数字开头 */
    if (tab_digit[look_ahead])
    {
        lex->symbol.type = symbol_type_num;
        if(look_ahead == '0')
        {
            look_ahead = input_buf_get_char(lex->input_buf);
            if((look_ahead == 'x') 
                || (look_ahead == 'X'))
            {
                lex->symbol.name[name_len++] = '0';
                lex->symbol.name[name_len++] = look_ahead;
                while (tab_hex[look_ahead = input_buf_get_char(lex->input_buf)])
                {
                    lex->symbol.value = lex->symbol.value * 16 
                        + (tab_hex2digit[look_ahead]);
                    if (name_len < (sizeof(lex->symbol.name) - 1))
                    {
                        lex->symbol.name[name_len++] = look_ahead;
                    }
                }
                if(name_len == 2)
                {
                    ERR_FUNC_LINE("line: %d, data err: %c\n", lex->line, look_ahead);
                    return NULL;
                }
                if(look_ahead != '\0')
                {
                    input_buf_goback(lex->input_buf);
                }
                lex->symbol.name[name_len++] = '\0';
                return &(lex->symbol);
            }
            else 
            {
                lex->symbol.name[name_len++] = '0';
                if(tab_digit[look_ahead] == 0)
                {
                    if(look_ahead != '\0')
                    {
                        input_buf_goback(lex->input_buf);
                    }
                    lex->symbol.name[name_len++] = '\0';
                    return &(lex->symbol);
                }
            }
        }

        lex->symbol.name[name_len++] = look_ahead;
        lex->symbol.value = lex->symbol.value * 10 + (look_ahead - '0');
        while (tab_digit[look_ahead = input_buf_get_char(lex->input_buf)])
        {
            lex->symbol.value = lex->symbol.value * 10 + (look_ahead - '0');
            if (name_len < (sizeof(lex->symbol.name) - 1))
            {
                lex->symbol.name[name_len++] = look_ahead;
            }
        }
        if(look_ahead != '\0')
        {
            input_buf_goback(lex->input_buf);
        }
    }
    else if (look_ahead == '+')
    {
        lex->symbol.name[name_len++] = look_ahead;
        look_ahead = input_buf_get_char(lex->input_buf);
        if (look_ahead == '+')
        {
            lex->symbol.name[name_len++] = look_ahead;
            lex->symbol.type = symbol_type_increase;
        }
        else
        {
            if(look_ahead != '\0')
            {
                input_buf_goback(lex->input_buf);
            }
            lex->symbol.type = symbol_type_plus;
        }
    }
    else if (look_ahead == '-')
    {
        lex->symbol.name[name_len++] = look_ahead;
        look_ahead = input_buf_get_char(lex->input_buf);
        if (look_ahead == '-')
        {
            lex->symbol.name[name_len++] = look_ahead;
            lex->symbol.type = symbol_type_decrease;
        }
        else
        {
            if(look_ahead != '\0')
            {
                input_buf_goback(lex->input_buf);
            }
            lex->symbol.type = symbol_type_minus;
        }
    }
    else if (look_ahead == '*')
    {
        lex->symbol.name[name_len++] = look_ahead;
        lex->symbol.type = symbol_type_multiply;
    }
    else if (look_ahead == '/')
    {
        lex->symbol.name[name_len++] = look_ahead;
        lex->symbol.type = symbol_type_divide;
    }
    else if (look_ahead == '%')
    {
        lex->symbol.name[name_len++] = look_ahead;
        lex->symbol.type = symbol_type_surplus;
    }
    else if (look_ahead == '(')
    {
        lex->symbol.name[name_len++] = look_ahead;
        lex->symbol.type = symbol_type_open_parenthesis;
    }
    else if (look_ahead == ')')
    {
        lex->symbol.name[name_len++] = look_ahead;
        lex->symbol.type = symbol_type_close_parenthesis;
    }
    else if (look_ahead == '[')
    {
        lex->symbol.name[name_len++] = look_ahead;
        lex->symbol.type = symbol_type_open_bracket;
    }
    else if (look_ahead == ']')
    {
        lex->symbol.name[name_len++] = look_ahead;
        lex->symbol.type = symbol_type_close_bracket;
    }
    else if (look_ahead == '{')
    {
        lex->symbol.name[name_len++] = look_ahead;
        lex->symbol.type = symbol_type_open_brace;
    }
    else if (look_ahead == '}')
    {
        lex->symbol.name[name_len++] = look_ahead;
        lex->symbol.type = symbol_type_close_brace;
    }
    else if (look_ahead == '\'')
    {
        look_ahead = input_buf_get_char(lex->input_buf);
        lex->symbol.type = symbol_type_character;
        /* 转义 */
        if(look_ahead == '\\')
        {
            look_ahead = input_buf_get_char(lex->input_buf);
            if(look_ahead == '0')
            {
                lex->symbol.name[name_len++] = '\0';
            }
            else
            {
                lex->symbol.name[name_len++] = look_ahead;
            }
        }
        else
        {
            lex->symbol.name[name_len++] = look_ahead;
        }

        look_ahead = input_buf_get_char(lex->input_buf);
        if(look_ahead != '\'')
        {
            ERR_FUNC_LINE("line: %d, data err: %c\n", lex->line, look_ahead);
            return NULL;
        }
    }
    else if (look_ahead == '.')
    {
        lex->symbol.name[name_len++] = look_ahead;
        lex->symbol.type = symbol_type_point;
    }
    else if (look_ahead == '"')
    {
        lex->symbol.type = symbol_type_string;
        while ('\0' != (look_ahead = input_buf_get_char(lex->input_buf)))
        {
            if(look_ahead == '\\')
            {
                lex->symbol.name[name_len++] = look_ahead;
                look_ahead = input_buf_get_char(lex->input_buf);
                lex->symbol.name[name_len++] = look_ahead;
            }
            else if(look_ahead == '"')
            {
                break;
            }
            else
            {
                lex->symbol.name[name_len++] = look_ahead;
            }
        }
    }
    else if (look_ahead == ',')
    {
        lex->symbol.name[name_len++] = look_ahead;
        lex->symbol.type = symbol_type_dot;
    }
    else if (look_ahead == ';')
    {
        lex->symbol.name[name_len++] = look_ahead;
        lex->symbol.type = symbol_type_semicolon;
    }
    else if (look_ahead == '=')
    {
        lex->symbol.name[name_len++] = look_ahead;
        look_ahead = input_buf_get_char(lex->input_buf);
        if (look_ahead == '=')
        {
            lex->symbol.name[name_len++] = look_ahead;
            lex->symbol.type = symbol_type_assign;
        }
        else
        {
            if(look_ahead != '\0')
            {
                input_buf_goback(lex->input_buf);
            }
            lex->symbol.type = symbol_type_equal;
        }
    }
    else if (look_ahead == '>')
    {
        lex->symbol.name[name_len++] = look_ahead;
        look_ahead = input_buf_get_char(lex->input_buf);
        if (look_ahead == '=')
        {
            lex->symbol.name[name_len++] = look_ahead;
            lex->symbol.type = symbol_type_more_equal;
        }
        else
        {
            if(look_ahead != '\0')
            {
                input_buf_goback(lex->input_buf);
            }
            lex->symbol.type = symbol_type_more;
        }
    }
    else if (look_ahead == '<')
    {
        lex->symbol.name[name_len++] = look_ahead;
        look_ahead = input_buf_get_char(lex->input_buf);
        if (look_ahead == '=')
        {
            lex->symbol.name[name_len++] = look_ahead;
            lex->symbol.type = symbol_type_less_equal;
        }
        else
        {
            if(look_ahead != '\0')
            {
                input_buf_goback(lex->input_buf);
            }
            lex->symbol.type = symbol_type_less;
        }
    }
    else if (look_ahead == '!')
    {
        lex->symbol.name[name_len++] = look_ahead;
        look_ahead = input_buf_get_char(lex->input_buf);
        if (look_ahead == '=')
        {
            lex->symbol.name[name_len++] = look_ahead;
            lex->symbol.type = symbol_type_not_equal;
        }
        else
        {
            if(look_ahead != '\0')
            {
                input_buf_goback(lex->input_buf);
            }
            lex->symbol.type = symbol_type_not;
        }
    }
    /* 字母开头的 */
    else if (tab_alpha[look_ahead])
    {
        lex->symbol.type = symbol_type_id;
        lex->symbol.name[name_len++] = look_ahead;
        while (tab_id[look_ahead = input_buf_get_char(lex->input_buf)])
        {
            if (name_len < (sizeof(lex->symbol.name) - 1))
            {
                lex->symbol.name[name_len++] = look_ahead;
            }
        }
        lex->symbol.name[name_len++] = '\0';
        lex->symbol.type = keywords_get_symbol_type(lex->symbol.name, 
            strlen((char *)lex->symbol.name));
        if(look_ahead != '\0')
        {
            input_buf_goback(lex->input_buf);
        }
    }
    else if (look_ahead == '&')
    {
        lex->symbol.name[name_len++] = look_ahead;
        look_ahead = input_buf_get_char(lex->input_buf);
        if (look_ahead == '&')
        {
            lex->symbol.name[name_len++] = look_ahead;
            lex->symbol.type = symbol_type_and;
        }
        else
        {
            if(look_ahead != '\0')
            {
                input_buf_goback(lex->input_buf);
            }
            lex->symbol.type = symbol_type_bits_and;
        }
    }
    else if (look_ahead == '|')
    {
        lex->symbol.name[name_len++] = look_ahead;
        look_ahead = input_buf_get_char(lex->input_buf);
        if (look_ahead == '|')
        {
            lex->symbol.name[name_len++] = look_ahead;
            lex->symbol.type = symbol_type_or;
        }
        else
        {
            if(look_ahead != '\0')
            {
                input_buf_goback(lex->input_buf);
            }
            lex->symbol.type = symbol_type_bits_or;
        }
    }
    else
    {
        if (look_ahead != '\0')
        {
            ERR_FUNC_LINE("line: %d, data err: %c\n", lex->line, look_ahead);
        }
        return NULL;
    }

    lex->symbol.name[name_len++] = '\0';
    return &(lex->symbol);
}

/**
 * @brief 将look ahead的symbol放回到lex中
 *
 * @param lex 待操作的lex_st结构体指针
 * @param symbol 待放回的symbol
 * @return int32_t: 0 放回成功; <0 放回失败
 */
int32_t lex_put_symbol(
    lex_st *lex,
    symbol_st *symbol)
{
    if (lex->lookahead_symbol != NULL)
    {
        ERR_FUNC_LINE("line: %d, ERR!lookahead_symbol of lex isn't NULL!\n", lex->line);
        return -1;
    }
    lex->lookahead_symbol = symbol;
    return 0;
}

/**
 * @brief 释放lex_st结构体
 *
 * @param lex 待释放的lex_st结构体指针
 */
void lex_free(
    lex_st *lex)
{
    if (lex == NULL)
    {
        return;
    }

    if (lex->input_buf != NULL)
    {
        input_buf_free(lex->input_buf);
    }

    my_free(lex);
}

/**
 * @brief 根据测试文件路径，初始化一个lex
 *
 * @param path 测试文件路径
 * @return lex_st* 申请的lex结构体
 */
lex_st *lex_malloc(
    char *path)
{
    lex_st *lex = my_calloc(sizeof(lex_st), 1);
    if (lex == NULL)
    {
        ERR_FUNC_LINE("line: %d, calloc lex err!\n", lex->line);
        return NULL;
    }
    lex->input_buf = input_buf_malloc(path);
    if (lex->input_buf == NULL)
    {
        lex_free(lex);
        return NULL;
    }
    lex->line = 1;
    return lex;
}

/**
 * @brief lex_st 测试函数
 *
 */
void lex_test(
    void)
{
    FUNC_BEGIN();
    char *path = "./test_data.txt";
    lex_st *lex = lex_malloc(path);
    assert(lex != NULL);

    symbol_st *symbol = NULL;
    while (NULL != (symbol = lex_get_symbol(lex)))
    {
        NOTICE("symbol type: %-20s, symbol value: %-10ld, symbol name: %s\n",
               symbol_type_str(symbol->type), symbol->value, symbol->name);
    }
    lex_free(lex);
    lex = NULL;
    FUNC_FINISH();
}